# Factory Pattern (2) Abstract Factory Pattern

Assembled by GimunLee

νŒ©ν† λ¦¬ λ©”μ†Œλ“œ νŒ¨ν„΄κ³Ό μ΄μ–΄μ§€λ―€λ‘œ, μ•ž μž₯을 미리 읽고 μ˜€μ‹œλŠ” 것을 μΆ”μ²œν•©λ‹ˆλ‹€.

# Goal

  • Abstract Factory Pattern의 κ°œλ…μ„ μ•Œ 수 μžˆλ‹€.
  • Abstract Factory Pattern에 λŒ€ν•΄ μ„€λͺ…ν•  수 μžˆλ‹€.
  • νŒ©ν† λ¦¬ λ©”μ†Œλ“œ νŒ¨ν„΄κ³Ό 좔상 νŒ©ν† λ¦¬ νŒ¨ν„΄μ˜ 차이점에 λŒ€ν•΄ μ„€λͺ…ν•  수 μžˆλ‹€.

# ν”Όμžκ°€κ²Œ 뢄점 문제점

각 λΆ„μ μ—μ„œ ν”Όμžμ˜ 재료λ₯Ό λ‹€λ₯Έ 것을 μ‚¬μš©ν•˜κΈ° μ‹œμž‘ν–ˆμŠ΅λ‹ˆλ‹€. μ΄λ ‡κ²Œ μ„œλ‘œ λ‹€λ₯Έ μ’…λ₯˜μ˜ μž¬λ£Œλ“€μ„ μ œκ³΅ν•˜κΈ° μœ„ν•΄ μ›μž¬λ£Œκ΅°(families of ingredients)을 μ²˜λ¦¬ν•  방법을 생각해 봐야 ν•©λ‹ˆλ‹€.

# 문제점

  • λͺ¨λ“  ν”ΌμžλŠ” 같은 κ΅¬μ„±μš”μ†Œλ‘œ μ΄λ£¨μ–΄μ§€μ§€λ§Œ, μ§€μ—­λ§ˆλ‹€ 각 κ΅¬μ„±μš”μ†Œλ₯Ό λ‹€λ₯Έ λ°©μ‹μœΌλ‘œ κ΅¬ν˜„ν•©λ‹ˆλ‹€.
  • 각 κ΅°(family)은 νŠΉμ • ν˜•μ‹μ˜ 반죽, νŠΉμ • ν˜•μ‹μ˜ μ†ŒμŠ€, 치즈 그리고 ν•΄μ‚°λ¬Ό ν† ν•‘μœΌλ‘œ κ΅¬μ„±λ©λ‹ˆλ‹€. (κ·Έ 외에도 μ•Όμ±„λ‚˜ ν–₯μ‹ λ£Œ 같은 μžμž˜ν•œ 것듀이 μžˆμŠ΅λ‹ˆλ‹€.)
  • 각 뢄점은 각각의 μ›μž¬λ£Œκ΅°μ„ μ΄λ£Ήλ‹ˆλ‹€. 각 μ§€μ—­λ§ˆλ‹€ νŠΉμ • ν˜•μ‹μ˜ 재료둜 κ΅¬μ„±λ˜λŠ” ꡰ을 κ΅¬ν˜„ν•΄μ•Όν•©λ‹ˆλ‹€.

# μ›μž¬λ£Œ 곡μž₯ λ§Œλ“€κΈ°

이제 μ›μž¬λ£Œλ₯Ό μƒμ‚°ν•˜κΈ° μœ„ν•œ 곡μž₯을 λ§Œλ“€μ–΄ λ³΄κ² μŠ΅λ‹ˆλ‹€. 이 곡μž₯μ—μ„œλŠ” μ›μž¬λ£Œκ΅°μ— λ“€μ–΄μžˆλŠ” 각각의 μ›μž¬λ£Œλ₯Ό μƒμ‚°ν•©λ‹ˆλ‹€. 즉, 반죽, μ†ŒμŠ€, 치즈 같은 κ±Έ λ§Œλ“€μ–΄μ•Ό ν•©λ‹ˆλ‹€.

μš°μ„  λͺ¨λ“  μ›μž¬λ£Œλ₯Ό 생산할 νŒ©ν† λ¦¬λ₯Ό μœ„ν•œ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ •μ˜ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

  • 각 μž¬λ£Œλ³„ 생성 λ©”μ†Œλ“œλ₯Ό μ •μ˜ν•©λ‹ˆλ‹€.
  • λͺ¨λ“  νŒ©ν† λ¦¬ μΈμŠ€ν„΄μŠ€μ—μ„œ κ³΅ν†΅μ μœΌλ‘œ μ‚¬μš©ν•˜λŠ” 뢀뢄이 μžˆλ‹€λ©΄ μΈν„°νŽ˜μ΄μŠ€κ°€ μ•„λ‹Œ μΆ”μƒν΄λž˜μŠ€λ‘œ λ§Œλ“€μ–΄λ„ λ©λ‹ˆλ‹€.
public interface PizzaIngredientFactory {
  public Dough createDough();
  public Sauce createSauce();
  public Cheese createCheese();
  public Veggies[] createVeggies();
  public Pepperoni createPepperoni();
  public Clams createClam();
}

뉴μ˜₯ μ›μž¬λ£Œ 곡μž₯을 κ΅¬ν˜„ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€. 이 곡μž₯μ—μ„œλŠ” λ§ˆλ¦¬λ‚˜λΌ μ†ŒμŠ€, λ ˆμ§€μ•„λ…Έ 치즈, μ‹ μ„ ν•œ 쑰개 등을 μ „λ¬Έμ μœΌλ‘œ μƒμ‚°ν•©λ‹ˆλ‹€.

public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
  public Dough createDough() {
    return new ThinCrustDough();
  }
  
  public Sauce createSauce() {
    return new MarinaraSauce();
  }
  
  public Cheese createCheese() {
    return new ReggianoCheese();
  }
  
  public Veggies[] createVeggies(){
  	Veggies veggies[] = { new Garlic(), new Onion(), new Mushroom(), new RedPepper() };
    return veggies;
  }
  
  public Pepperoni createPepperoni() {
    return new SlicedPepperoni();
  }
  
  public Clams createClam() {
    return new FreshClams();
  }
}

# ν”Όμž 클래슀 λ³€κ²½

νŒ©ν† λ¦¬ μ€€λΉ„κ°€ λλ‚˜κ³  이제 재료λ₯Ό 생산할 μ€€λΉ„κ°€ λλ‚¬μŠ΅λ‹ˆλ‹€. Pizza ν΄λž˜μŠ€μ— νŒ©ν† λ¦¬μ—μ„œ μƒμ‚°ν•œ μ›μž¬λ£Œλ§Œ μ‚¬μš©ν•˜λ„λ‘ μ½”λ“œλ₯Ό κ³ μ³μ•Όν•©λ‹ˆλ‹€. μš°μ„  Pizza 좔상 ν΄λž˜μŠ€μ—μ„œ μ‹œμž‘ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

public abstract class Pizza {
  String name;
  Dough dough;
  Sauce sauce;
  Veggies veggies[];
  Cheese cheese;
  Pepperoni pepperoni;
  Clams clam;
  
  abstract void prepare(); // 이 λΆ€λΆ„μ—μ„œ ν”Όμžλ₯Ό λ§Œλ“œλŠ”λ° ν•„μš”ν•œ μž¬λ£Œλ“€μ„ μ •λˆν•˜κ²Œ λ©λ‹ˆλ‹€. λ¬Όλ‘  λͺ¨λ“  μ›μž¬λ£ŒλŠ” μ›μž¬λ£Œ νŒ©ν† λ¦¬μ—μ„œ κ°€μ Έμ˜΅λ‹ˆλ‹€.
  
  void bake(){
    System.out.println("Bake for 25 minutes at 350");
  }
  
  void cut(){
    System.out.println("Cutting the pizza into diagonal slices");
  }
  
  void box(){
    System.out.println("Place pizza in official PizzaStore box");
  }
  
  void setName(String name){
    this.name = name;
  }
  
  String getName(){
    return name;
  }
  
  public String toString(){
    // ν”Όμž 이름을 좜λ ₯ν•˜λŠ” λΆ€λΆ„
  }
}
  • prepare() λ©”μ†Œλ“œλ₯Ό μ œμ™Έν•œ λ‹€λ₯Έ λ©”μ†Œλ“œλ“€μ€ λ°”λ€Œμ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

Pizza 좔상 클래슀 μ€€λΉ„κ°€ λλ‚¬μœΌλ‹ˆ 뉴μ˜₯풍 ν”Όμžμ™€ μ‹œμΉ΄κ³ ν’ ν”Όμžλ₯Ό λ§Œλ“€μ–΄μ•Όλ©λ‹ˆλ‹€. 달라진 점은 μ›μž¬λ£Œλ₯Ό 곡μž₯μ—μ„œ λ°”λ‘œ κ°€μ Έμ˜¨λ‹€λŠ” 것 밖에 μ—†μŠ΅λ‹ˆλ‹€.

νŒ©ν† λ¦¬ λ©”μ†Œλ“œ νŒ¨ν„΄μ„ μ΄μš©ν•œ μ½”λ“œλ₯Ό λ§Œλ“€μ—ˆμ„ λ•Œ, λ‹€λ₯Έ ν”Όμž 클래슀λ₯Ό μ‚΄νŽ΄λ³΄λ©΄ μ§€μ—­λ³„λ‘œ λ‹€λ₯Έ 재료λ₯Ό μ‚¬μš©ν•œλ‹€λŠ” κ²ƒλ§Œ λΉΌλ©΄ λ‹€λ₯Έμ μ΄ μ—†μŠ΅λ‹ˆλ‹€. ν”Όμžλ₯Ό μ΄λ£¨λŠ” κΈ°λ³Έ μš”μ†Œκ°€ 반죽, μ†ŒμŠ€, μΉ˜μ¦ˆλΌλŠ” 건 λ§ˆμ°¬κ°€μ§€λ‹ˆκΉŒμš”. 야채 ν”Όμžλ‚˜ 쑰개 ν”Όμžλ„ λ§ˆμ°¬κ°€μ§€μž…λ‹ˆλ‹€. 재료만 λ‹€λ₯Ό 뿐 μ€€λΉ„ 단계듀을 λ˜‘κ°™μŠ΅λ‹ˆλ‹€.

λ”°λΌμ„œ ν”Όμžλ§ˆλ‹€ 클래슀λ₯Ό μ§€μ—­λ³„λ‘œ λ§Œλ“€ ν•„μš”κ°€ μ—†λ‹€λŠ” 결둠을 내릴 수 μžˆμŠ΅λ‹ˆλ‹€. μ§€μ—­λ³„λ‘œ λ‹€λ₯Έ 점은 μ›μž¬λ£Œ 곡μž₯μ—μ„œ μ»€λ²„ν•΄μ£Όλ‹ˆκΉŒμš”. 치즈 ν”Όμž μ½”λ“œλ₯Ό κ΅¬ν˜„ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

public class CheesePizza extends Pizza {
  PizzaIngredientFactory ingredientFactory;
  
  // 이제 ν”Όμžλ₯Ό λ§Œλ“€κΈ° μœ„ν•΄ μ›μž¬λ£Œλ₯Ό μ œκ³΅ν•˜λŠ” 곡μž₯이 ν•„μš”ν•©λ‹ˆλ‹€. 
  // λ”°λΌμ„œ 각 ν”Όμž ν΄λž˜μŠ€μ—μ„œλŠ” μƒμ„±μžλ₯Ό ν†΅ν•΄μ„œ νŒ©ν† λ¦¬λ₯Ό 전달 λ°›μŠ΅λ‹ˆλ‹€.
  public CheesePizza(PizzaIngredientFactory ingredientFactory) {
    this.ingredientFactory = ingredientFactory;  
  }
  
  void prepare(){
    System.out.println("Preparing " + name);
    dough = ingredientFactory.createDough();
    sauce = ingredientFactory.createSauce();
    cheese = ingredientFactory.createCheese();
  }
}

# μ˜¬λ°”λ₯Έ 재료 곡μž₯ μ‚¬μš©ν•˜κΈ°

ν”Όμž κ°€κ²Œλ₯Ό λ‹€μ‹œ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

public class NYPizzaStore extends PizzaStore {
  
  protected Pizza createPizza(String item) {
    Pizza pizza = null;
    PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory();
    
    if(item.equals("cheese")){
    	pizza = new CheesePizza(ingredientFactory);
      pizza.setName("New York Style Cheese Pizza");
    }else if(item.equals("veggie")){
      pizza = new VeggiePizza(ingredientFactory);
      pizza.setName("New York Style Veggie Pizza");
    }else if(item.equals("clam")){
      pizza = new ClamPizza(ingredientFactory);
      pizza.setName("New York Style Clam Pizza");
    }else if(item.equals("pepperoni")){
      pizza = new PepperoniPizza(ingredientFactory);
      pizza.setName("New York Style Pepperoni Pizza");
    }
    return pizza;
  }
}

νŒ©ν† λ¦¬ λ©”μ†Œλ“œ νŒ¨ν„΄μ—μ„œ createPizza() λ©”μ†Œλ“œμ™€ λΉ„κ΅ν•΄λ³΄μ‹œκΈΈ λ°”λžλ‹ˆλ‹€.


# μ§€κΈˆκΉŒμ§€ ν•œ κ±Έ 정리해 λ΄…μ‹œλ‹€.

좔상 νŒ©ν† λ¦¬(Abstract Factory)라고 λΆ€λ₯΄λŠ” μƒˆλ‘œμš΄ ν˜•μ‹μ˜ νŒ©ν† λ¦¬λ₯Ό λ„μž…ν•΄μ„œ μ„œλ‘œ λ‹€λ₯Έ ν”Όμžμ—μ„œ ν•„μš”λ‘œ ν•˜λŠ” μ›μž¬λ£Œκ΅°μ„ μƒμ‚°ν•˜κΈ° μœ„ν•œ 방법을 κ΅¬μΆ•ν–ˆμŠ΅λ‹ˆλ‹€.

좔상 νŒ©ν† λ¦¬λ₯Ό ν†΅ν•΄μ„œ μ œν’ˆκ΅°μ„ μƒμ„±ν•˜κΈ° μœ„ν•œ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ œκ³΅ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 이 μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ΄μš©ν•˜λŠ” μ½”λ“œλ₯Ό λ§Œλ“€λ©΄ μ½”λ“œλ₯Ό μ œν’ˆμ„ μƒμ‚°ν•˜λŠ” μ‹€μ œ νŒ©ν† λ¦¬μ™€ λΆ„λ¦¬μ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λ ‡κ²Œ ν•¨μœΌλ‘œμ¨ (지역, 운영체제, 룩앀필 λ“±) μ„œλ‘œ λ‹€λ₯Έ μƒν™©λ³„λ‘œ μ λ‹Ήν•œ μ œν’ˆμ„ 생산할 수 μžˆλŠ” λ‹€μ–‘ν•œ νŒ©ν† λ¦¬λ₯Ό κ΅¬ν˜„ν•  수 있게 λ©λ‹ˆλ‹€.

μ½”λ“œκ°€ μ‹€μ œ μ œν’ˆν•˜κ³  λΆ„λ¦¬λ˜μ–΄ μžˆμœΌλ―€λ‘œ λ‹€λ₯Έ 곡μž₯을 μ‚¬μš©ν•˜κΈ°λ§Œ ν•˜λ©΄ λ‹€λ₯Έ κ²°κ³Όλ₯Ό 얻을 수 μžˆμŠ΅λ‹ˆλ‹€.


# 좔상 νŒ©ν† λ¦¬ νŒ¨ν„΄ μ •μ˜

이제 ν•œ 가지 νŒ©ν† λ¦¬ νŒ¨ν„΄μ„ 더 λ°°μ› μŠ΅λ‹ˆλ‹€. μ œν’ˆκ΅°μ„ λ§Œλ“€ λ•Œ μ“Έ 수 μžˆλŠ” νŒ¨ν„΄μž…λ‹ˆλ‹€.

좔상 νŒ©ν† λ¦¬ νŒ¨ν„΄ - 좔상 νŒ©ν† λ¦¬ νŒ¨ν„΄μ—μ„œλŠ” μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ΄μš©ν•˜μ—¬ μ„œλ‘œ μ—°κ΄€λœ, λ˜λŠ” μ˜μ‘΄ν•˜λŠ” 객체λ₯Ό ꡬ상 클래슀λ₯Ό μ§€μ •ν•˜μ§€ μ•Šκ³ λ„ 생성할 수 μžˆμŠ΅λ‹ˆλ‹€.

좔상 νŒ©ν† λ¦¬ νŒ¨ν„΄μ„ μ‚¬μš©ν•˜λ©΄ ν΄λΌμ΄μ–ΈνŠΈμ—μ„œ 좔상 μΈν„°νŽ˜μ΄μŠ€λ₯Ό ν†΅ν•΄μ„œ 일련의 μ œν’ˆλ“€μ„ 곡급받을 수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λ•Œ, μ‹€μ œλ‘œ μ–΄λ–€ μ œν’ˆμ΄ μƒμ‚°λ˜λŠ”μ§€λŠ” μ „ν˜€ μ•Œ ν•„μš”λ„ μ—†μŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ ν΄λΌμ΄μ–ΈνŠΈμ™€ νŒ©ν† λ¦¬μ—μ„œ μƒμ‚°λ˜λŠ” μ œν’ˆμ„ λΆ„λ¦¬μ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.

클래슀 λ‹€μ΄μ–΄κ·Έλž¨μ„ ν†΅ν•΄μ„œ μ–΄λ–€ μ‹μœΌλ‘œ λŒμ•„κ°€λŠ”μ§€ μ‚΄νŽ΄λ΄…μ‹œλ‹€.

이제 PizzaStoreκΉŒμ§€ ν¬ν•¨μ‹œμΌœμ„œ 전체적인 λ‹€μ΄μ–΄κ·Έλž¨μ„ μ‚΄νŽ΄λ΄…μ‹œλ‹€.


좔상 νŒ©ν† λ¦¬ νŒ¨ν„΄ λ’€μ—λŠ” νŒ©ν† λ¦¬ λ©”μ†Œλ“œ νŒ¨ν„΄μ΄ μˆ¨μ–΄μžˆλŠ” κ±΄κ°€μš”?

좔상 νŒ©ν† λ¦¬ νŒ¨ν„΄μ—μ„œ λ©”μ†Œλ“œκ°€ νŒ©ν† λ¦¬ λ©”μ†Œλ“œλ‘œ κ΅¬ν˜„λ˜λŠ” κ²½μš°λ„ μ’…μ’… μžˆμŠ΅γ„΄λ””γ…. 좔상 νŒ¨ν† λ¦¬κ°€ μ›λž˜ 일련의 μ œν’ˆλ“€μ„ μƒμ„±ν•˜λŠ” 데 쓰일 μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ •μ˜ν•˜κΈ° μœ„ν•΄ λ§Œλ“€μ–΄μ§„ κ±°λ‹ˆκΉŒμš”. κ·Έ μΈν„°νŽ˜μ΄μŠ€μ— μžˆλŠ” 각 λ©”μ†Œλ“œλŠ” ꡬ상 μ œν’ˆμ„ μƒμ‚°ν•˜λŠ” 일을 맑고 있고, 좔상 νŒ©ν† λ¦¬μ˜ μ„œλΈŒν΄λž˜μŠ€λ₯Ό λ§Œλ“€μ–΄μ„œ 각 λ©”μ†Œλ“œμ˜ κ΅¬ν˜„μ„ μ œκ³΅ν•©λ‹ˆλ‹€. λ”°λΌμ„œ 좔상 νŒ©ν† λ¦¬ νŒ¨ν„΄μ—μ„œ μ œν’ˆμ„ μƒμ‚°ν•˜κΈ° μœ„ν•œ λ©”μ†Œλ“œλ₯Ό κ΅¬ν˜„ν•˜λŠ” 데 μžˆμ–΄μ„œ νŒ©ν† λ¦¬ λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•˜λŠ” 것은 λ„ˆλ¬΄λ‚˜λ„ μžμ—°μŠ€λŸ¬μš΄ μΌμž…λ‹ˆλ‹€.


# 클래슀 λ‹€μ΄μ–΄κ·Έλž¨ 비ꡐ

# νŒ©ν† λ¦¬ λ©”μ†Œλ“œ νŒ¨ν„΄

# 좔상 νŒ©ν† λ¦¬ νŒ¨ν„΄


# References

  • Head First Design Patterns
Last Updated: 8/12/2020, 1:33:42 PM